<?php
/***************************************************************************
 * 
 * Copyright (c) 2010 , Inc. All Rights Reserved
 * $Id$ 
 * 
 **************************************************************************/



/**
 * @file Validation.php
 * @author niulei(niulei@)
 * @date 2010/05/17 18:58:28
 * @version $Revision$ 
 * @brief 
 *  
 **/
require_once dirname(__FILE__)."/ValidationFunc.php";
require_once dirname(__FILE__)."/ValidationFuncRef.php";

final class Validation {
	static $FUNC_INPUT_ARRAY = array(
	                             'STRING' => self::STRING,
	                             'FLOAT' => self::FLOAT,
		                         'INT' =>self::INT,
	                             'NUMBER'=>self::NUMBER,
	                             'STRING_UNHTML' => self::STRING_UNHTML,
	                             'STRING_SINGLE' => self::STRING_SINGLE,
	                             'STRING_MULTI' => self::STRING_MULTI,
	                             'IDNUM' => self::IDNUM,
	                             'NAME' => self::NAME,
	                             'EMAIL' => self::EMAIL,
	                             'TELNO' => self::TELNO,
	                             'ADDRESS' => self::ADDRESS,
	                             'ADDLEVEL1' => self::ADDLEVEL1,
	                             'ADDLEVEL2' => self::ADDLEVEL2,
	                             'ADDLEVEL3' => self::ADDLEVEL3,
	                             'BIRTH' => self::BIRTH,
	                             'PHONENO' => self::PHONENO,	                            
	                           );
	static $FLAG_INPUT_ARRAY = array(
	                              'FLAG_CASE_IGNORE' => self::FLAG_CASE_IGNORE,
	                              'FLAG_ALLOW_EMPTY' => self::FLAG_ALLOW_EMPTY,
	                              'FLAG_ALLOW_HIGH' => self::FLAG_ALLOW_HIGH,
	                              'FLAG_ALLOW_LOW' => self::FLAG_ALLOW_LOW,
	                              'FLAG_ALLOW_ENTER' => self::FLAG_ALLOW_ENTER,
	                              'FLAG_ALLOW_ALL' => self::FLAG_ALLOW_ALL,
	                              'FLAG_ALLOW_OCTAL' => self::FLAG_ALLOW_OCTAL,
	                              'FLAG_ALLOW_HEX' => self::FLAG_ALLOW_HEX,
	                              'FLAG_ALLOW_THOUSAND' => self::FLAG_ALLOW_THOUSAND,
	                                  );
	/*
	 * validation function定义
	 */
	const STRING = "string_validation";
	const FLOAT = "float_validation";
	const INT = "int_validation";
	const NUMBER = "number_validation";
	const STRING_UNHTML = "string_unhtml_validation";
	const STRING_SINGLE = "string_single_validation";
	const STRING_MULTI = "string_multi_validation";
	const IDNUM = "idnum_validation";
	const NAME = "name_validation";
	const EMAIL = "email_validation";
	const TELNO = "tel_no_validation";
	const ADDRESS = "address_validation";
	const ADDLEVEL1 = "address_level1_validation";
	const ADDLEVEL2 = "address_level2_validation";
	const ADDLEVEL3 = "address_level3_validation";
	const BIRTH = "birthday_validation";
	const PHONENO = "phone_no_validation";

	/*
	 * validation flag定义
	 */
	//忽略大小写
	const FLAG_CASE_IGNORE = 128;
	//允许为空
	const FLAG_ALLOW_EMPTY = 64;
	//允许汉字
	const FLAG_ALLOW_HIGH = 32;
	//允许低字节字符，即不可见字符
	const FLAG_ALLOW_LOW = 8;
	//不允许低字节字符，除了tab,回车和换行
	const FLAG_ALLOW_ENTER = 16;
    //允许所有
	const FLAG_ALLOW_ALL = 255;
	//允许8进制
	const FLAG_ALLOW_OCTAL = FILTER_FLAG_ALLOW_OCTAL;//1
	//允许16进制
	const FLAG_ALLOW_HEX = FILTER_FLAG_ALLOW_HEX;//2
	//允许千位分隔符
	const FLAG_OFFSET = 8188;
	const FLAG_ALLOW_THOUSAND = 4;

    static $VALIDATION_FUNC_ARRAY = array(
			                                self::STRING => 1,
								            self::FLOAT => 1,
								            self::INT => 1,
								            self::NUMBER => 1,
								            self::STRING_UNHTML => 1,
								            self::STRING_SINGLE => 1,
								            self::STRING_MULTI => 1,
								            self::NAME => 1,
								            self::IDNUM => 1,
								            self::EMAIL => 1,
								            self::TELNO => 1,
								            self::ADDRESS => 1,
								            self::ADDLEVEL1 => 1,
								            self::ADDLEVEL2 => 1,
								            self::ADDLEVEL3 => 1,
								            self::BIRTH => 1,
								            self::PHONENO => 1,
								           );
   
    static $VALIDATION_FUNC_FLAG = array(
                                            self::FLAG_ALLOW_THOUSAND,
                                            self::FLAG_ALLOW_ALL,
                                            self::FLAG_ALLOW_EMPTY,
                                            self::FLAG_ALLOW_ENTER,
                                            self::FLAG_ALLOW_HEX,
                                            self::FLAG_ALLOW_HIGH,
                                            self::FLAG_ALLOW_LOW,
                                            self::FLAG_ALLOW_OCTAL,
                                            self::FLAG_CASE_IGNORE
                                          );

	/**
	 * check用户选择指定的规则对输入字符串进行校验
	 * 
	 * @param string $input 输入的要校验的数据,该接口只支持单个输入
	 * @param string $arr_rules  输入校验规则
	 *         $arr_rules = array(
	 *                              'func'=>1,//必选
	 *                              'flag'=>2,//可选
	 *                              'min_range'=>1,
	 *                              'max_range'=>2,
	 *                              'encode'=>'gbk'|'utf-8',//可选编码，不设置按gbk处理
	 *                              'reg_exp'=>[可输入一个PHP支持的正则表达式],
	 *                              'length_array'=>array(2,3,5),//可选长度值
	 *                              'byte_length'=>true|false,//是否按字节长度处理，不设置不采用字节长度处理
	 *                              ...
	 *                            )
	 * @access public
	 * @return 
	 *         true :校验通过
	 *         other : 校验错误描述,供调试使用
	 */
    public static function check($input, $arr_rules = null){
    	if(!isset($arr_rules['func'])){
    		throw new Exception("validation.FuncNotDefined");
    	}else{
    		if(is_array($arr_rules['func'])){
    			throw new Exception("validation.FuncNotSupportArray");
    		}
    		if(!isset(self::$FUNC_INPUT_ARRAY[$arr_rules['func']]))
    		    throw new Exception("validation.FuncNotExist");
    		$func = self::$FUNC_INPUT_ARRAY[$arr_rules['func']];
    	}
    	$flag = array();
    	if(isset($arr_rules['flag'])){
    	    $flag = $arr_rules['flag'];
    	    unset($arr_rules['flag']);
    	}
        
    	if(!ValidationFunc::checkValidationFunc($func)){
    		throw new Exception("validation.FuncNotExist");
    	}
    	if(!ValidationFunc::checkValidationFlag($flag)){
    		throw new Exception("validation.FlagNotExist");
    	}
    	//将多个选项进行组合
    	if(is_array($flag)){
    		$new_flag = 0;
    		foreach ($flag as $flag_item) {
    			$new_flag = $new_flag | self::$FLAG_INPUT_ARRAY[$flag_item];
    		}
    	}else{
    		$new_flag = self::$FLAG_INPUT_ARRAY[$flag];
    	}
    	$validate_res = Validation::FAIL_NONE;
    	if(!ValidationFunc::$func($input, $arr_rules, $new_flag, $arr_rules['func'], $validate_res)){
    		return $validate_res;
    	}else
    	    return true;
    }

	/**
	 * check_array用户选择指定的规则对输入字符串进行校验
	 * 
	 * @param string $input 输入的要校验的数据,该接口支持数组输入
	 * @param string $arr_rules  输入校验规则,根据$input里的key值设定rules
	 *         $arr_rules = array(
	 *                              'key' => array(
	 *                                            'func'=>1,//必选
	 *                                            'flag'=>2,//可选
	 *                                            'min_range'=>1,
	 *                                            'max_range'=>2,
	 *                                            'encode'=>'gbk'|'utf-8',//可选编码，不设置按gbk处理
	 *                                            'reg_exp'=>[可输入一个PHP支持的正则表达式],
	 *                                            'length_array'=>array(2,3,5),//可选长度值
	 *                                            'byte_length'=>true|false,//是否按字节长度处理，不设置不采用字节长度处理
	 *                                            ...
	 *                              )
	 *                            )
	 * @access public
	 * @return $arr_check_res = array (
	 *                                   'key' => true | [fail类型]
	 *                                 )
	 */
    public static function checkArray($arr_input = array(), $arr_rules = array()){
    	$arr_check_res = array();
    	foreach ($arr_rules as $key => $value) {
    		if(!array($value)){
    			throw new Exception("validation.CheckArrayRulesOnlySupportArray");
    		}
    		if(isset($value['flag']) && is_array($value['flag']) && in_array("FLAG_ALLOW_EMPTY", $value['flag'])){
    			if(isset($arr_input[$key])){//如果输入的key存在
    				$check_res = self::check($arr_input[$key], $value);
    			    $arr_check_res[$key] = $check_res;
    			}else{
    				$arr_check_res[$key] = true;
    			}
    		}elseif (isset($value['flag']) && !is_array($value['flag']) && "FLAG_ALLOW_EMPTY"==$value['flag']){
    		    if(isset($arr_input[$key])){//如果输入的key存在
    				$check_res = self::check($arr_input[$key], $value);
    			    $arr_check_res[$key] = $check_res;
    			}else{
    				$arr_check_res[$key] = true;
    			}
    		}else{//需要检查input输入的key存在
    		    if(isset($arr_input[$key])){//如果输入的key存在
    				$check_res = self::check($arr_input[$key], $value);
    			    $arr_check_res[$key] = $check_res;
    			}else{
    				$arr_check_res[$key] = "error:" . Validation::FAIL_EXIST;
    			}
    		}
    	}
    	return $arr_check_res;
    }

    //检测未通过信息
    const FAIL_NONE = "None checked";
    const FAIL_EMPTY = "Empty checked";
    const FAIL_LENGTH = "Length checked";
    const FAIL_VALUE = "Value checked";
    const FAIL_ENCODE = "Encode checked";
    const FAIL_REGEXP = "Regexp checked";
    const FAIL_CONTENT = "Content checked";
    const FAIL_THOUSAND = "Thousand checked";
    const FAIL_EXIST = "Exist checked";
}

/* vim: set ts=4 sw=4 sts=4 tw=100 noet: */
